/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.editor.field;

import com.daikit.daikit4gxt.client.DkBaseMain;
import com.daikit.daikit4gxt.client.ui.editor.advanced.AbstractDkHideableAdapterField;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.sencha.gxt.core.client.util.ToggleGroup;
import com.sencha.gxt.widget.core.client.form.Radio;


/**
 * A boolean editor displayed as a RadioGroup
 *
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public class RadioGroupField extends AbstractDkHideableAdapterField<Boolean> implements HasValueChangeHandlers<Boolean>
{

	private final ToggleGroup toggleGroup;

	private final Radio choiceYes = new Radio();
	private final Radio choiceNo = new Radio();
	private final Radio choiceUndefined = new Radio();

	private final int height = 26;

	private boolean enabled = true;

	/**
	 * Create a new Radio group field with default labels (Yes/No). The Empty choice is not displayed.
	 */
	public RadioGroupField()
	{
		this(false);
	}

	/**
	 * Create a new radio group field with given labels. The Empty choice is not displayed.
	 *
	 * @param yesChoiceLabel
	 *           the label for Yes choice
	 * @param noChoiceLabel
	 *           the label for No choice
	 */
	public RadioGroupField(final String yesChoiceLabel, final String noChoiceLabel)
	{
		this(false);
		setYesChoiceLabel(yesChoiceLabel);
		setNoChoiceLabel(noChoiceLabel);
	}

	/**
	 * Create a new radio group field with given labels. The Empty choice is displayed.
	 *
	 * @param yesChoiceLabel
	 *           the label for Yes choice
	 * @param noChoiceLabel
	 *           the label for No choice
	 * @param undefinedChoiceLabel
	 *           the label for empty choice
	 */
	public RadioGroupField(final String yesChoiceLabel, final String noChoiceLabel, final String undefinedChoiceLabel)
	{
		this(true);
		setYesChoiceLabel(yesChoiceLabel);
		setNoChoiceLabel(noChoiceLabel);
		setUndefinedChoiceLabel(undefinedChoiceLabel);
	}

	/**
	 * Create a new Radio group field with default labels (Yes/No). The empty choice is displayed regarding
	 * displayEmptyChoice value.
	 *
	 * @param displayEmptyChoice
	 *           to add a third choice for <b><code>null</code></b> value.
	 */
	public RadioGroupField(final boolean displayEmptyChoice)
	{
		super(new HorizontalPanel());
		setYesChoiceLabel(DkBaseMain.i18n().label_yes());
		setNoChoiceLabel(DkBaseMain.i18n().label_no());
		setUndefinedChoiceLabel(DkBaseMain.i18n().label_undefined());
		final HorizontalPanel panel = (HorizontalPanel) getWidget();
		toggleGroup = new ToggleGroup();
		toggleGroup.add(choiceYes);
		toggleGroup.add(choiceNo);
		panel.add(choiceYes);
		panel.add(choiceNo);
		if (displayEmptyChoice)
		{
			toggleGroup.add(choiceUndefined);
			panel.add(choiceUndefined);
		}
		choiceYes.setValue(Boolean.TRUE);
		choiceNo.setValue(Boolean.FALSE);
		choiceUndefined.setValue(null);

		setHeight(height);

		choiceYes.addValueChangeHandler(new ValueChangeHandler<Boolean>()
		{
			@Override
			public void onValueChange(final ValueChangeEvent<Boolean> event)
			{
				ValueChangeEvent.fire(RadioGroupField.this, event.getValue());
			}
		});
		choiceNo.addValueChangeHandler(new ValueChangeHandler<Boolean>()
		{
			@Override
			public void onValueChange(final ValueChangeEvent<Boolean> event)
			{
				ValueChangeEvent.fire(RadioGroupField.this, event.getValue());
			}
		});
		choiceUndefined.addValueChangeHandler(new ValueChangeHandler<Boolean>()
		{
			@Override
			public void onValueChange(final ValueChangeEvent<Boolean> event)
			{
				ValueChangeEvent.fire(RadioGroupField.this, event.getValue());
			}
		});
	}

	@Override
	public void setValue(final Boolean value)
	{
		if (value == null)
		{
			toggleGroup.setValue(choiceUndefined);
		}
		else if (value.booleanValue())
		{
			toggleGroup.setValue(choiceYes);
		}
		else
		{
			toggleGroup.setValue(choiceNo);
		}
	}

	@Override
	public Boolean getValue()
	{
		final HasValue<Boolean> choiceSelected = toggleGroup.getValue();
		return choiceYes.equals(choiceSelected) ? Boolean.TRUE : choiceNo.equals(choiceSelected) ? Boolean.FALSE : null;
	}

	@Override
	public void setEnabled(final boolean enabled)
	{
		choiceUndefined.setEnabled(enabled);
		choiceYes.setEnabled(enabled);
		choiceNo.setEnabled(enabled);
		this.enabled = enabled;
	}

	@Override
	public boolean isEnabled()
	{
		return enabled;
	}

	@Override
	public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<Boolean> handler)
	{
		return addHandler(handler, ValueChangeEvent.getType());
	}

	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
	// GETTERS / SETTERS
	// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

	/**
	 * @param yesChoiceLabel
	 *           the yesChoiceLabel to set
	 */
	public void setYesChoiceLabel(final String yesChoiceLabel)
	{
		choiceYes.setBoxLabel(yesChoiceLabel);
	}

	/**
	 * @param noChoiceLabel
	 *           the noChoiceLabel to set
	 */
	public void setNoChoiceLabel(final String noChoiceLabel)
	{
		choiceNo.setBoxLabel(noChoiceLabel);
	}

	/**
	 * @param undefinedChoiceLabel
	 *           the undefinedChoiceLabel to set
	 */
	public void setUndefinedChoiceLabel(final String undefinedChoiceLabel)
	{
		choiceUndefined.setBoxLabel(undefinedChoiceLabel);
	}
}
